<template>
  <div class="node-editor" @contextmenu.prevent="showContextMenu">
    <!-- 节点编辑器容器 -->
    <div v-if="contextMenu.visible" 
         class="context-menu" 
         :style="{ left: `${contextMenu.x}px`, top: `${contextMenu.y}px` }">
      <div class="menu-item" @click="createNode('flow')">流程节点</div>
      <div class="menu-item" @click="createNode('procedure')">过程节点</div>
      <div class="menu-item" @click="createNode('product')">产品节点</div>
    </div>
    
    <!-- 连接线渲染 -->
    <Connection
      v-for="connection in connections"
      :key="connection.id"
      :connection="connection"
      :source-node="findNodeById(connection.source)"
      :target-node="findNodeById(connection.target)"
      @select="handleConnectionSelect"
    />
    
    <!-- 节点渲染 -->
    <Node
      v-for="node in nodes"
      :key="node.id"
      :node="node"
      :is-selected="selectedNode && selectedNode.id === node.id"
      @select="handleNodeSelect"
      @update:position="updateNodePosition"
      @connection-created="handleConnectionCreated"
    />
  </div>
</template>

<script>
import Node from './Node.vue';
import Connection from './Connection.vue';
import { NodeTypes, NodeConfigs } from './NodeTypes';

export default {
  name: 'NodeEditor',
  components: {
    Node,
    Connection
  },
  data() {
    return {
      nodes: [],
      connections: [],
      contextMenu: {
        visible: false,
        x: 0,
        y: 0
      },
      draggingNode: null,
      dragOffsetX: 0,
      dragOffsetY: 0,
      selectedNode: null,
      draggingSourceNode: null
    }
  },
  mounted() {
    document.addEventListener('click', this.handleGlobalClick);
    document.addEventListener('keydown', this.handleKeyDown);
  },
  beforeDestroy() {
    document.removeEventListener('click', this.handleGlobalClick);
    document.removeEventListener('keydown', this.handleKeyDown);
  },
  methods: {
    handleNodeSelect(node) {
      this.selectedNode = node;
      this.selectedConnection = null;
    },
    
    handleConnectionSelect(connection) {
      this.selectedConnection = connection;
      this.selectedNode = null;
    },
    
    findNodeById(nodeId) {
      return this.nodes.find(node => node.id === nodeId);
    },
    
    showContextMenu(e) {
      e.stopPropagation();
      this.contextMenu = {
        visible: true,
        x: e.clientX,
        y: e.clientY
      };
    },
    
    hideContextMenu() {
      this.contextMenu.visible = false;
    },
    
    handleGlobalClick(e) {
      const contextMenuEl = document.querySelector('.context-menu');
      if (contextMenuEl && !contextMenuEl.contains(e.target)) {
        this.hideContextMenu();
      }
      
      // 如果点击空白处，取消节点选中
      const nodeEl = e.target.closest('.node');
      if (!nodeEl) {
        this.selectedNode = null;
      }
    },
    
    createNode(type) {
      let nodeType;
      switch(type) {
        case 'flow':
          nodeType = NodeTypes.FLOW.SOLID;
          break;
        case 'procedure':
          nodeType = NodeTypes.PROCESS;
          break;
        case 'product':
          nodeType = NodeTypes.PRODUCT;
          break;
      }

      const config = NodeConfigs[nodeType];
      const nodeConfig = {
        ...config,
        x: this.contextMenu.x,
        y: this.contextMenu.y
      }
      
      this.addNode(nodeConfig);
      this.hideContextMenu();
    },
    
    addNode(node) {
      this.nodes.push({
        ...node,
        id: Date.now().toString(),
        x: node.x,
        y: node.y
      });
    },
    
    removeNode(nodeId) {
      this.nodes = this.nodes.filter(node => node.id !== nodeId);
      this.connections = this.connections.filter(
        conn => conn.source !== nodeId && conn.target !== nodeId
      );
    },
    
    updateNodePosition(nodeId, position) {
      const node = this.nodes.find(n => n.id === nodeId);
      if (node) {
        node.x = position.x;
        node.y = position.y;
      }
    },
    
    addConnection(connection) {
      if (this.validateConnection(connection)) {
        this.connections.push({
          ...connection,
          id: `${connection.source}-${connection.target}`
        });
      }
    },
    
    removeConnection(connectionId) {
      this.connections = this.connections.filter(
        conn => conn.id !== connectionId
      );
    },
    
    validateConnection({ sourceNodeId, sourcePortIndex, targetNodeId, targetPortIndex }) {
      // 防止自连接
      if (sourceNodeId === targetNodeId) return false;
      
      // 获取节点实例
      const sourceNode = this.findNodeById(sourceNodeId);
      const targetNode = this.findNodeById(targetNodeId);
      
      // 验证节点类型兼容性
      const isTypeValid = ConnectionRules[sourceNode.type]?.canConnectTo.includes(targetNode.type);
      
      // 验证端口类型匹配
      const sourcePort = sourceNode.outputs[sourcePortIndex];
      const targetPort = targetNode.inputs[targetPortIndex];
      const isPortValid = sourcePort?.type === 'exec' && targetPort?.type === 'exec';
      
      // 防止重复连接
      const existing = this.connections.find(
        conn => conn.source === sourceNodeId && 
               conn.sourcePortIndex === sourcePortIndex &&
               conn.target === targetNodeId &&
               conn.targetPortIndex === targetPortIndex
      );
      
      return isTypeValid && isPortValid && !existing;
    },

    handleConnectionCreated({ source, sourcePortIndex, target, targetPortIndex }) {
      const connection = {
        source,
        sourcePortIndex,
        target,
        targetPortIndex
      };
      
      if (this.validateConnection(connection)) {
        this.connections.push({
          id: `${source}-${sourcePortIndex}-${target}-${targetPortIndex}`,
          ...connection
        });
      }
      this.draggingSourceNode = null;
    },
    
    handleKeyDown(e) {
      // 当按下Delete键且有选中节点时，删除节点
      if (e.key === 'Delete' && this.selectedNode) {
        this.removeNode(this.selectedNode.id);
        this.selectedNode = null;
      }
    },
    
    updateNodePosition({ id, position }) {
      const node = this.nodes.find(n => n.id === id);
      if (node) {
        node.x = position.x;
        node.y = position.y;
      }
    }
  }
}
</script>

<style>
@import '../assets/styles/NodeEditor.css';
</style>